package org.duang.handles;

import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.duang.config.Config;
import org.duang.db.mongo.Mongo;
import org.duang.kit.ToolsKit;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.security.SecurityHelper;
import com.security.ShiroUser;

/**
 * 框架日志处理器
 * @author laotang
 */
public class MvcLogHandle implements IHandle {

	private Set<String> filterUrls;								// 不作记录的URL请求路径集合
	private DBCollection mvcLogCollection;						// 日志表对象
	private static final String MVCLOG_COLL = "sys_mvclogs";	// 表名
	
	public MvcLogHandle() {
		this.filterUrls = new HashSet<String>();
		filterUrls.add(Config.getSecurityLoginUrl());			// 登录Action路径
		filterUrls.add(Config.getSecurityLoginInUrl());			// 提交登录URL
		filterUrls.add(Config.getSecurityLoginOutUrl());		// 退出登录URL
		filterUrls.add(Config.getSecurityUnauthorizedUrl());	// 验证出错URL
		String[] urls = Config.getNotSecurityFilterUrls();			// 不作验证URL,即定时器调用的URI
		for(String url : urls){
			filterUrls.add(url);
		}
	}
	
	public MvcLogHandle(Set<String> filterUrls) {
		this.filterUrls = new HashSet<String>();
		this.filterUrls.addAll(filterUrls);
	}
	
	private DBCollection getMvcLogCollection(){
		if(ToolsKit.isEmpty(mvcLogCollection)){
			DB db = Mongo.getInstance().getDB();
			mvcLogCollection = db.getCollection(MVCLOG_COLL);
			if(null == mvcLogCollection) {
				mvcLogCollection = db.createCollection(MVCLOG_COLL, null);
			}
			// 创建索引
			carateIndex("target");
			carateIndex("createusername");
		}
		return mvcLogCollection;
	}
	
	private void carateIndex(String key) {
		String name = "_"+key+"_";
		String type = "1";
		String order = "asc";
		DBObject keys = new BasicDBObject(key, "asc".equals(order) ? Integer.parseInt("1") : Integer.parseInt("-1"));
		if("2d".equals(type)) keys.put(key, type);
		DBObject options = new BasicDBObject("background", true);
		options.put("name", name.toLowerCase());        		
		options.put("unique", false);
		mvcLogCollection.createIndex(keys, options);
	}
	
	@Override
	public void execute(String target, HttpServletRequest request, HttpServletResponse response) throws Exception {		
		if(ToolsKit.isEmpty(target) || filterUrls.contains(target) || !ToolsKit.isSecurityUrl(target)){
			return;
		}
		DBObject log = new BasicDBObject();
		log.put("target", target);
		log.put("contenttype", ToolsKit.isEmpty(request.getContentType()) ? "" : request.getContentType());
		log.put("method", request.getMethod());
		log.put("params", getAllValue(request));
		log.put("createtime", new Date());
		String client = request.getHeader("X-Real-IP");
		client = ToolsKit.isEmpty(client) ? request.getRemoteHost() :  client;
		log.put("client", client);
		if(Config.getEnadleSecurity()){
			try{
				ShiroUser sUser = SecurityHelper.getShiroUser();
				if(ToolsKit.isNotEmpty(sUser)){
					log.put("createusername", sUser.getAccount());
					log.put("createuserid", sUser.getUserid());
				}
			}catch(Exception ex){
				ex.printStackTrace();
			}
		}
		getMvcLogCollection().insert(log);
	}
	
	 private Map<String, Object> getAllValue(HttpServletRequest request) {
	        Map<String, Object> paramMap = new HashMap<String, Object>();
	        Enumeration<String> enumer = request.getParameterNames();
	        if (ToolsKit.isNotEmpty(enumer)) {
	            while (enumer.hasMoreElements()) {
	                String key = enumer.nextElement();
	                String value = request.getParameter(key);
	                paramMap.put(key, value);
	            }
	        }
//	        enumer = request.getAttributeNames();
//	        if (ToolUtil.isNotEmpty(enumer)) {
//	            while (enumer.hasMoreElements()) {
//	                String key = enumer.nextElement();
//	                if(key.indexOf("Filter") == -1 || key.indexOf("Shiro") == -1){
//	                	Object value = request.getAttribute(key);
//	                	paramMap.put(key, value);
//	                }
//	            }
//	        }
	        return paramMap;
	    }

}
